[TDR Generic表][Go SDK]批量更新多条数据
1. 接口说明
BatchUpdate,向数据库表中批量更新多条记录,记录不存在报错
注意:
- 最多批量操作1024条记录;
- 单条记录的错误码在调用response的FetchRecord时返回
- 调用request的方法SetMultiResponseFlag()设置允许分包,否则,响应包超过256KB不分包会丢包
- 当响应包超过256KB会触发分包。但保证分包不会切分单个记录(不管这个记录多大),例如,响应包的3个记录分别是10KB、251KB、1MB,会分为2个包返回,即(10KB、251KB)和(1MB); 可调用TcaplusServiceResponse::HaveMoreResPkgs()判断是否还有下一个包
- batch类的操作都是非原子操作,只要有一个记录执行成功,总的执行结果就是成功,但是响应包中会给出每条记录的执行结果及错误码。
更多说明参见批量操作接口的相关说明。
2. 版本要求
3.55.0以上版本的SDK
3. 准备工作
参见准备工作文档,完成使用该接口前的准备工作,并创建如下TDR Generic表。service_info表service_info.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<metalib name="service_info" tagsetversion="1" version="1">
<struct name="service_info" version="1" primarykey="gameid,envdata,name,expansion" splittablekey="gameid" >
<entry name="gameid" type="string" size="128" desc="gameapp id"/>
<entry name="envdata" type="string" size="1024" desc="env环境信息" />
<entry name="name" type="string" size="1024" desc="名字" />
<entry name="expansion" type="string" size="1024" desc="扩展字段" />
<entry name="filterdata" type="string" size="1024" desc="过滤标签" />
<entry name="updatetime" type="uint64" desc="最近更新时间,单位ms" />
<entry name="inst_max_num" type="uint64" desc="最大实例个数" />
<entry name="inst_min_num" type="uint64" desc="最小实例个数" />
<entry name="routeinfo_len" type="uint" defaultvalue="0" desc="路由规则信息长度" />
<entry name="routeinfo" type="char" count="1024" refer="routeinfo_len" desc="路由规则信息" />
<index name="index_gameid_envdata_name" column="gameid,envdata,name" />
<index name="index_gameid_envdata" column="gameid,envdata" />
<index name="index_gameid_name" column="gameid,name" />
<index name="index_gameid" column="gameid" />
</struct>
</metalib>
准备工作完成后,将会获得以下信息,这些信息在使用SDK时会被用到:
- 目录服务器地址列表
- 业务ID
- 业务访问密码
- 游戏区ID
- 数据表名
4. 示例代码
示例代码的基本执行过程:
- 定义表配置参数
- 设置日志配置;
- 创建客户端;
- 发送请求并处理响应;
- 销毁客户端。
客户端初始化示例:
package main
import (
"fmt"
"git.woa.com/gcloud_storage_group/tcaplus-go-api"
)
// 定义表配置参数
const (
AppId = uint64(2)
ZoneId = uint32(3)
DirUrl = "tcp://x.x.x.x:xxxx"
Signature = "xxxxxxxxxxxxx"
TableName = "service_info"
)
var client *tcaplus.Client
func main() {
// 创建客户端
client = tcaplus.NewClient()
// 设置日志配置,logconf.xml文件设置了日志级别
if err := client.SetLogCfg("./logconf.xml"); err != nil {
fmt.Println(err.Error())
return
}
// 连接TcaplusDB后端
err := client.Dial(AppId, []uint32{ZoneId}, DirUrl, Signature, 60)
if err != nil {
fmt.Printf("init failed %v\n", err.Error())
return
}
fmt.Printf("Dial finish\n")
batchUpdateExample()
// 程序退出时调用Close销毁客户端
client.Close()
}
4.1 同步调用示例(推荐)
同步调用编码最简单,通过多协程并发 示例目录
package main
import (
"fmt"
"git.woa.com/gcloud_storage_group/tcaplus-go-api/example/TDR/async/service_info"
"git.woa.com/gcloud_storage_group/tcaplus-go-api/protocol/option"
"git.woa.com/gcloud_storage_group/tcaplus-go-api/record"
"time"
)
func batchUpdateExample() {
//result flag + version success
opt := &option.TDROpt{
ResultFlagForSuccess: option.TcaplusResultFlagAllOldValue,
VersionPolicy: option.CheckDataVersionAutoIncrease,
}
var dataSlice []record.TdrTableSt
for i := 0; i < 10; i++ {
data := service_info.NewService_Info()
data.Gameid = "dev"
data.Envdata = "oa"
data.Name = fmt.Sprintf("%d", i)
data.Filterdata = "update"
data.Updatetime = uint64(time.Now().UnixNano())
data.Inst_Max_Num = 2
data.Inst_Min_Num = 3
route := "test"
data.Routeinfo_Len = uint32(len(route))
data.Routeinfo = []byte(route)
dataSlice = append(dataSlice, data)
opt.BatchVersion = append(opt.BatchVersion, 2) //校验version
}
if err := client.DoBatchUpdate(TableName, dataSlice, opt); err != nil {
fmt.Println(err.Error())
return
}
fmt.Println(opt.BatchResult)
for _, data := range dataSlice {
fmt.Printf("%+v", data)
}
fmt.Println("Batch Update SUCCESS")
}
4.2 同步调用示例2(推荐)
该示例同步调用方式比较类似C++接口的调用方式,需要创建请求和解析响应示例目录
package main
import (
"fmt"
"git.woa.com/gcloud_storage_group/tcaplus-go-api/example/TDR/async/service_info"
"git.woa.com/gcloud_storage_group/tcaplus-go-api/protocol/cmd"
"git.woa.com/gcloud_storage_group/tcaplus-go-api/terror"
"strconv"
"time"
)
func batchUpdateExample() {
//创建请求
req, err := client.NewRequest(ZoneId, TableName, cmd.TcaplusApiBatchUpdateReq)
if err != nil {
fmt.Printf("NewRequest TcaplusApiGetReq failed %v\n", err.Error())
return
}
//允许分包
req.SetMultiResponseFlag(1)
// 请求标志。0标志只需返回成功与否,1标志返回同请求一致的值,2标志返回操作后所有字段的值,3标志返回操作前所有字段的值
req.SetResultFlagForSuccess(2)
for i:=0; i < 10; i++ {
//为request添加一条记录,最多1024
rec, err := req.AddRecord(0)
if err != nil {
fmt.Printf("AddRecord failed %v\n", err.Error())
return
}
//申请tdr结构体并赋值Key,最好调用tdr pkg的NewXXX函数,会将成员初始化为tdr定义的tdr默认值,
// 不要自己new,自己new,某些结构体未初始化,存在panic的风险
data := service_info.NewService_Info()
data.Gameid = "dev"
data.Envdata = fmt.Sprintf("%d", i)
data.Name = "com"
data.Filterdata = time.Now().Format("2006-01-02T15:04:05.000000Z")
data.Updatetime = uint64(time.Now().UnixNano())
data.Inst_Max_Num = 2
data.Inst_Min_Num = 3
//数组类型为slice需要准确赋值长度,与refer保持一致
route := "test"
data.Routeinfo_Len = uint32(len(route))
data.Routeinfo = []byte(route)
if err := rec.SetData(data); err != nil {
fmt.Printf("SetData failed %v\n", err.Error())
return
}
}
respList, err := client.DoMore(req, time.Duration(10*time.Second))
if err != nil {
fmt.Printf("recv err %s\n", err.Error())
}
var totalCnt int = 0
for _, resp := range respList {
tcapluserr := resp.GetResult()
if tcapluserr != 0 {
fmt.Printf("response ret %s\n",
"errCode: "+strconv.Itoa(tcapluserr)+", errMsg: "+terror.ErrorCodes[tcapluserr])
break
}
totalCnt += resp.GetRecordCount()
record, err := resp.FetchRecord()
if err != nil {
fmt.Printf("FetchRecord failed %s\n", err.Error())
return
}
//通过GetData获取记录
data := service_info.NewService_Info()
if err := record.GetData(data); err != nil {
fmt.Printf("record.GetData failed %s\n", err.Error())
return
}
fmt.Printf("response record data %+v, route: %s\n",
data, string(data.Routeinfo[0:data.Routeinfo_Len]))
}
fmt.Printf("total count %d,\n", totalCnt)
}
4.3 异步调用示例
异步发送可以使用较少的协程实现较大的并发,编码相对复杂,示例目录
package main
import (
"fmt"
"git.woa.com/gcloud_storage_group/tcaplus-go-api/example/TDR/async/service_info"
"git.woa.com/gcloud_storage_group/tcaplus-go-api/logger"
"git.woa.com/gcloud_storage_group/tcaplus-go-api/protocol/cmd"
"git.woa.com/gcloud_storage_group/tcaplus-go-api/terror"
"strconv"
"sync"
"time"
)
func batchUpdateExample() {
wg := sync.WaitGroup{}
wg.Add(1)
// 在另一协程处理响应消息
go func() {
defer wg.Done()
for {
// resp err 均为 nil 说明响应池中没有任何响应
resp, err := client.RecvResponse()
if err != nil {
logger.ERR("RecvResponse error:%s", err)
continue
} else if resp == nil {
time.Sleep(time.Microsecond * 5)
continue
}
//带回请求的异步ID
fmt.Printf("resp success, AsyncId:%d\n", resp.GetAsyncId())
tcapluserr := resp.GetResult()
if tcapluserr != 0 {
fmt.Printf("response ret %s\n",
"errCode: "+strconv.Itoa(tcapluserr)+", errMsg: "+terror.ErrorCodes[tcapluserr])
return
}
//response中带有获取的记录
fmt.Printf("response success record count %d\n", resp.GetRecordCount())
for i := 0; i < resp.GetRecordCount(); i++ {
record, err := resp.FetchRecord()
if err != nil {
fmt.Printf("FetchRecord failed %s\n", err.Error())
return
}
//通过GetData获取记录
data := service_info.NewService_Info()
if err := record.GetData(data); err != nil {
fmt.Printf("record.GetData failed %s\n", err.Error())
return
}
fmt.Printf("response record data %+v, route: %s\n",
data, string(data.Routeinfo[0:data.Routeinfo_Len]))
}
//判断是否有分包
if 1 == resp.HaveMoreResPkgs() {
continue
}
return
}
}()
//创建请求
req, err := client.NewRequest(ZoneId, TableName, cmd.TcaplusApiBatchUpdateReq)
if err != nil {
fmt.Printf(" NewRequest failed %v\n", err.Error())
return
}
//允许分包
req.SetMultiResponseFlag(1)
// 请求标志。0标志只需返回成功与否,1标志返回同请求一致的值,2标志返回操作后所有字段的值,3标志返回操作前所有字段的值
req.SetResultFlagForSuccess(2)
for i:=0; i < 10; i++ {
//为request添加一条记录,最多1024
rec, err := req.AddRecord(0)
if err != nil {
fmt.Printf(" AddRecord failed %v\n", err.Error())
return
}
//申请tdr结构体并赋值Key,最好调用tdr pkg的NewXXX函数,会将成员初始化为tdr定义的tdr默认值,
// 不要自己new,自己new,某些结构体未初始化,存在panic的风险
data := service_info.NewService_Info()
data.Gameid = "dev"
data.Envdata = fmt.Sprintf("%d", i)
data.Name = "com"
data.Filterdata = time.Now().Format("2006-01-02T15:04:05.000000Z")
data.Updatetime = uint64(time.Now().UnixNano())
data.Inst_Max_Num = 2
data.Inst_Min_Num = 3
//数组类型为slice需要准确赋值长度,与refer保持一致
route := "test"
data.Routeinfo_Len = uint32(len(route))
data.Routeinfo = []byte(route)
if err := rec.SetData(data); err != nil {
fmt.Printf("SetData failed %v\n", err.Error())
return
}
}
//发送请求
if err := client.SendRequest(req); err != nil {
fmt.Printf("SendRequest failed %v\n", err.Error())
return
}
wg.Wait()
}
5. 请求对象(request)中的方法说明
注:此处未列出请求对象的其它方法,即表示该方法在查询数据的场景不需要使用,误用可能会导致报错。
/**
@brief 向请求中添加一条记录。
@param [IN] index 用于List操作,通常>=0,表示该Record在所属List中的Index;
对于Generic操作,index无意义,设0即可
@retval record.Record 返回记录指针
@retval error 错误码
**/
AddRecord(index int32) (*record.Record, error)
/**
@brief 设置请求的异步事务ID,api会将其值不变地通过对应的响应消息带回来
@param [IN] asyncId 请求对应的异步事务ID
**/
SetAsyncId(id uint64)
/**
@brief 设置请求的通用标志位,可以通过"按位或"操作同时设定多个值
@param [IN] flag. 请求标志位的值
@retval 0 设置成功
@retval <0 失败,返回对应的错误码。通常因为未初始化。
@note 有效的标志位包括:
* TCAPLUS_FLAG_FETCH_ONLY_IF_MODIFIED:
* "数据变更才取回"标志位。在发起读操作之前,用户代码通过 TcaplusServiceRecord::SetVersion()
* 带上本地缓存数据的版本号,并将此标志置位,那么存储端检测到当前数据与API本地缓存的数据版本
* 一致时,表明该记录未发生过修改,API缓存的数据是最新的,因此在响应中将不会携带实际的数据,
* 只是返回 TcapErrCode::COMMON_INFO_DATA_NOT_MODIFIED 的错误码
*
* 在请求中设置了此标志位之后,收到响应后应首先通过 TcaplusServiceResponse::GetFlags() 来获知
* 发送请求时是否设置了TCAPLUS_FLAG_FETCH_ONLY_IF_MODIFIED标志.
*
* 只有如下请求支持设置此标志:
* TCAPLUS_API_GET_REQ,
* TCAPLUS_API_LIST_GET_REQ,
* TCAPLUS_API_LIST_GETALL_REQ
*
* TCAPLUS_FLAG_FETCH_ONLY_IF_EXPIRED:
* "数据过期才取回"标志位。在发起读操作之前,用户代码通过 SetExpireTime() 设定数据过期时间,
* 并将此标志置位,那么存储端若检测到记录在指定时间内发生过更新,则将数据返回,
* 否则不返回实际数据,只是返回 TcapErrCode::COMMON_INFO_DATA_NOT_MODIFIED 的错误码。
*
* 在请求中设置了此标志位之后,收到响应后应首先通过 TcaplusServiceResponse::GetFlags() 来获知
* 发送请求时是否设置了 TCAPLUS_FLAG_FETCH_ONLY_IF_EXPIRED 标志.
*
* 只有如下请求支持设置此标志:
* TCAPLUS_API_BATCH_GET_REQ
*
* TCAPLUS_FLAG_ONLY_READ_FROM_SLAVE
* 设置此标志后,读请求将会直接发送给Tcapsvr Slave 节点。
* Tcapsvr Slave 通常比较空闲,设置此标志有助于充分利用Tcapsvr Slave 资源。
*
* 适用场景:
* 对于数据实时性要求不高的读请求,
* 包括generic表和list表的所有读请求以及batchget,遍历请求
*
* TCAPLUS_FLAG_LIST_RESERVE_INDEX_HAVING_NO_ELEMENTS
* 设置此标志后,List表删除最后一个元素时需要保留index和version。
* ListDelete ListDeleteBatch ListDeleteAll操作在删除list表最后一个元素时,
* 设置此标志在写入新的List记录时,版本号依次增长,不会被重置为1。
*
* 适用场景:
* 业务需要确定某个表在删除最后一个元素时是否需要保留index和version
* 主要涉及List表的使用体验
*
*/
SetFlags(flag int32) int
/**
@brief 清理请求的通用标志位,可以通过"按位或"操作同时设定多个值
@param [IN] flag. 请求标志位的值
@retval 0 设置成功
@retval <0 失败,返回对应的错误码。通常因为未初始化。
@note 有效的标志位列表及详细解释请参考 SetFlags()
*/
ClearFlags(flag int32) int
/**
@brief 获取请求的通用标志位
@return 返回请求的通用标志位
@note 有效的标志位列表及详细解释请参考 SetFlags()
*/
GetFlags() int32
/**
@brief 设置需要查询或更新的Value字段名称列表,即部分Value字段查询和更新,可用于get、replace、update操作。
@param [IN] valueNameList 需要查询或更新的字段名称列表
@retval error 错误码
@note 在使用该函数设置字段名时,字段名只能包含value字段名,不能包含key字段名;对于数组类型的字段,
refer字段和数组字段要同时设置或者同时不设置,否则容易数据错乱
**/
SetFieldNames(valueNameList []string) error
/**
@brief 设置用户缓存,响应消息将携带返回
@param [IN] userBuffer 用户缓存
@retval error 错误码
**/
SetUserBuff(userBuffer []byte) error
/**
@brief 设置记录版本的检查类型,用于乐观锁
@param [IN] type 版本检测类型,取值可以为:
CheckDataVersionAutoIncrease: 表示检测记录版本号,只有当record.SetVersion函数传入的参数
version的值>0,并且版本号与服务器端的版本号相同时,请求才会成功同时在服务器端该版本号会自增1;
如果record.SetVersion的version <=0,则仍然表示不关心版本号
NoCheckDataVersionOverwrite: 表示不检测记录版本号。
当record.SetVersion函数传入的参数version的值>0,覆盖服务端的版本号;
如果record.SetVersion的version <=0,则仍然表示不关心版本号
NoCheckDataVersionAutoIncrease: 表示不检测记录版本号,将服务器端的数据记录版本号自增1,
若服务器端新写入数据记录则新写入的数据记录的版本号为1
@retval error 错误码
@note 此函数适合Replace, Update操作
**/
SetVersionPolicy(p uint8) error
/**
@brief 设置响应标志。主要用于Generic表的insert、increase、replace、update、delete操作。
@param [IN] flag 请求标志:
0表示: 只需返回操作执行成功与否
1表示: 操作成功,响应返回与请求字段一致
2表示: 操作成功,响应返回变更记录的所有字段最新数据
3表示: 操作成功,响应返回变更记录的所有字段旧数据
@retval error 错误码
NOTE:SetResultFlag有历史包袱,某些场景并不准确,推荐使用SetResultFlagForSuccess
**/
SetResultFlag(flag int) error
/**
@brief 设置响应标志。主要是本次请求成功执行后返回给前端的数据
result_flag 的取值范围如下:
TCaplusValueFlag_NOVALUE = 0, // 不返回任何返回值
TCaplusValueFlag_SAMEWITHREQUEST = 1, // 返回同请求一致的值
TCaplusValueFlag_ALLVALUE = 2, // 返回tcapsvr端操作后所有字段的值
TCaplusValueFlag_ALLOLDVALUE = 3, // 返回tcapsvr端操作前所有字段的值
下面是各个支持的命令字在设置不同的result_flag下执行成功后返回给API端的数据详细情况:
1. TCAPLUS_API_INSERT_REQ TCAPLUS_API_BATCH_INSERT_REQ
如果设置的是TCaplusValueFlag_NOVALUE, 则操作成功后不返回数据
如果设置的是TCaplusValueFlag_SAMEWITHREQUEST, 则操作成功后返回和请求一致的数据
如果设置的是TCaplusValueFlag_ALLVALUE, 则操作成功后返回本次insert操作后的数据
如果设置的是TCaplusValueFlag_ALLOLDVALUE, 则操作成功后返回空数据
2. TCAPLUS_API_REPLACE_REQ TCAPLUS_API_BATCH_REPLACE_REQ
如果设置的是TCaplusValueFlag_NOVALUE, 则操作成功后不返回数据
如果设置的是TCaplusValueFlag_SAMEWITHREQUEST, 则操作成功后返回和请求一致的数据
如果设置的是TCaplusValueFlag_ALLVALUE, 则操作成功后返回本次replace操作后的数据
如果设置的是TCaplusValueFlag_ALLOLDVALUE, 则操作成功后返回tcapsvr端操作前的数据, 如果tcapsvr端没有数据,即返回为空
3. TCAPLUS_API_UPDATE_REQ TCAPLUS_API_BATCH_UPDATE_REQ
如果设置的是TCaplusValueFlag_NOVALUE, 则操作成功后不返回数据
如果设置的是TCaplusValueFlag_SAMEWITHREQUEST, 则操作成功后返回和请求一致的数据
如果设置的是TCaplusValueFlag_ALLVALUE, 则操作成功后返回本次update操作后的数据
如果设置的是TCaplusValueFlag_ALLOLDVALUE, 则操作成功后返回tcapsvr端操作前的数据
4. TCAPLUS_API_INCREASE_REQ
如果设置的是TCaplusValueFlag_NOVALUE, 则操作成功后不返回数据
如果设置的是TCaplusValueFlag_SAMEWITHREQUEST, 则操作成功后返回和请求一致的数据
如果设置的是TCaplusValueFlag_ALLVALUE, 则操作成功后返回本次increase操作后的数据
如果设置的是TCaplusValueFlag_ALLOLDVALUE, 则操作成功后返回tcapsvr端操作前的数据, 如果tcapsvr端没有数据,即返回为空
5. TCAPLUS_API_DELETE_REQ TCAPLUS_API_BATCH_DELETE_REQ
如果设置的是TCaplusValueFlag_NOVALUE, 则操作成功后不返回数据
如果设置的是TCaplusValueFlag_SAMEWITHREQUEST, 则操作成功后返回和请求一致的数据
如果设置的是TCaplusValueFlag_ALLVALUE, 则操作成功后返回空数据
如果设置的是TCaplusValueFlag_ALLOLDVALUE, 则操作成功后返回tcapsvr端操作前的数据
6. TCAPLUS_API_LIST_DELETE_BATCH_REQ
如果设置的是TCaplusValueFlag_NOVALUE, 则操作成功后不返回数据
如果设置的是TCaplusValueFlag_SAMEWITHREQUEST, 则操作成功后返回和请求一致的数据, 暂时没有实现
如果设置的是TCaplusValueFlag_ALLVALUE, 则操作成功后不返回数据
如果设置的是TCaplusValueFlag_ALLOLDVALUE, 则操作成功后返回tcapsvr端操作前的数据, 凡是本次成功删除的index对应的数据都会返回
7. TCAPLUS_API_LIST_ADDAFTER_REQ
如果设置的是TCaplusValueFlag_NOVALUE, 则操作成功后不返回数据
如果设置的是TCaplusValueFlag_SAMEWITHREQUEST, 则操作成功后返回和请求一致的数据, 暂时没有实现
如果设置的是TCaplusValueFlag_ALLVALUE, 则操作成功后, 返回本次插入的记录和本次淘汰的数据记录
如果设置的是TCaplusValueFlag_ALLOLDVALUE, 则操作成功后不返回数据
8. TCAPLUS_API_LIST_DELETE_REQ
如果设置的是TCaplusValueFlag_NOVALUE, 则操作成功后不返回数据
如果设置的是TCaplusValueFlag_SAMEWITHREQUEST, 则操作成功后返回和请求一致的数据, 暂时没有实现
如果设置的是TCaplusValueFlag_ALLVALUE, 则操作成功后返回空数据
如果设置的是TCaplusValueFlag_ALLOLDVALUE, 则操作成功后返回tcapsvr端listdelete前的数据
9. TCAPLUS_API_LIST_REPLACE_REQ
如果设置的是TCaplusValueFlag_NOVALUE, 则操作成功后不返回数据
如果设置的是TCaplusValueFlag_SAMEWITHREQUEST, 则操作成功后返回和请求一致的数据, 暂时没有实现
如果设置的是TCaplusValueFlag_ALLVALUE, 则操作成功后返回tcapsvr端listreplace后的数据
如果设置的是TCaplusValueFlag_ALLOLDVALUE, 则操作成功后返回tcapsvr端listreplace前的数据
10. TCAPLUS_API_LIST_REPLACE_BATCH_REQ
如果设置的是TCaplusValueFlag_NOVALUE, 操作成功后返回和请求一致的数据
如果设置的是TCaplusValueFlag_SAMEWITHREQUEST, 则操作成功后返回和请求一致的数据
如果设置的是TCaplusValueFlag_ALLVALUE, 则操作成功后返回tcapsvr端listreplace后的数据
如果设置的是TCaplusValueFlag_ALLOLDVALUE, 则操作成功后返回tcapsvr端listreplace前的数据
@param [IN] result_flag 请求标志:
0表示: 只需返回操作执行成功与否
1表示: 返回与请求字段一致
2表示: 须返回变更记录的所有字段最新数据
3表示: 须返回变更记录的所有字段旧数据
从而知道是哪个key对应的记录失败了
@retval 0 设置成功
@retval <0 失败,返回对应的错误码。通常因为未初始化。
*/
SetResultFlagForSuccess(result_flag byte) int
/**
@brief 设置响应标志。主要是本次请求执行失败后返回给前端的数据
result_flag 的取值范围如下:
TCaplusValueFlag_NOVALUE = 0, // 不返回任何返回值
TCaplusValueFlag_SAMEWITHREQUEST = 1, // 返回同请求一致的值
TCaplusValueFlag_ALLVALUE = 2, // 返回tcapsvr端操作后所有字段的值
TCaplusValueFlag_ALLOLDVALUE = 3, // 返回tcapsvr端操作前所有字段的值
下面是各个支持的命令字在设置不同的result_flag下执行失败后返回给API端的数据详细情况:
1. TCAPLUS_API_INSERT_REQ TCAPLUS_API_BATCH_INSERT_REQ
如果设置的是TCaplusValueFlag_NOVALUE, 则操作失败后不返回数据
如果设置的是TCaplusValueFlag_SAMEWITHREQUEST, 则操作失败后返回和请求一致的数据
如果设置的是TCaplusValueFlag_ALLVALUE, 不合理场景
如果设置的是TCaplusValueFlag_ALLOLDVALUE, 如果获取到了tcapsvr端的数据则返回tcpasvr端的数据,如果没有获取到tcapsvr端的数据则返回空
2. TCAPLUS_API_REPLACE_REQ TCAPLUS_API_BATCH_REPLACE_REQ
如果设置的是TCaplusValueFlag_NOVALUE, 则操作失败后不返回数据
如果设置的是TCaplusValueFlag_SAMEWITHREQUEST, 则操作失败后返回和请求一致的数据
如果设置的是TCaplusValueFlag_ALLVALUE, 不合理场景
如果设置的是TCaplusValueFlag_ALLOLDVALUE, 如果获取到了tcapsvr端的数据则返回tcpasvr端的数据,如果没有获取到tcapsvr端的数据则返回空
3. TCAPLUS_API_UPDATE_REQ TCAPLUS_API_BATCH_UPDATE_REQ
如果设置的是TCaplusValueFlag_NOVALUE, 则操作失败后不返回数据
如果设置的是TCaplusValueFlag_SAMEWITHREQUEST, 则操作失败后返回和请求一致的数据
如果设置的是TCaplusValueFlag_ALLVALUE, 不合理场景
如果设置的是TCaplusValueFlag_ALLOLDVALUE, 如果获取到了tcapsvr端的数据则返回tcpasvr端的数据,如果没有获取到tcapsvr端的数据则返回空
4. TCAPLUS_API_INCREASE_REQ
如果设置的是TCaplusValueFlag_NOVALUE, 则操作失败后不返回数据
如果设置的是TCaplusValueFlag_SAMEWITHREQUEST, 则操作失败后返回和请求一致的数据
如果设置的是TCaplusValueFlag_ALLVALUE, 不合理场景
如果设置的是TCaplusValueFlag_ALLOLDVALUE, 如果获取到了tcapsvr端的数据则返回tcpasvr端的数据,如果没有获取到tcapsvr端的数据则返回空
5. TCAPLUS_API_DELETE_REQ TCAPLUS_API_BATCH_DELETE_REQ
如果设置的是TCaplusValueFlag_NOVALUE, 则操作失败后不返回数据
如果设置的是TCaplusValueFlag_SAMEWITHREQUEST, 则操作失败后返回和请求一致的数据
如果设置的是TCaplusValueFlag_ALLVALUE, 不合理场景
如果设置的是TCaplusValueFlag_ALLOLDVALUE, 如果获取到了tcapsvr端的数据则返回tcpasvr端的数据,如果没有获取到tcapsvr端的数据则返回空
6. TCAPLUS_API_LIST_DELETE_BATCH_REQ
如果设置的是TCaplusValueFlag_NOVALUE, 则操作失败后不返回数据
如果设置的是TCaplusValueFlag_SAMEWITHREQUEST, 则操作失败后返回和请求一致的数据, 暂时没有实现
如果设置的是TCaplusValueFlag_ALLVALUE, 不合理场景
如果设置的是TCaplusValueFlag_ALLOLDVALUE, 则操作成功后返回tcapsvr端操作前的数据, 凡是本次成功删除的index对应的数据都会返回
7. TCAPLUS_API_LIST_ADDAFTER_REQ
如果设置的是TCaplusValueFlag_NOVALUE, 则操作失败后不返回数据
如果设置的是TCaplusValueFlag_SAMEWITHREQUEST, 则操作失败后返回和请求一致的数据, 暂时没有实现
如果设置的是TCaplusValueFlag_ALLVALUE, 不合理场景
如果设置的是TCaplusValueFlag_ALLOLDVALUE, 不返回数据
8. TCAPLUS_API_LIST_DELETE_REQ
如果设置的是TCaplusValueFlag_NOVALUE, 则操作失败后不返回数据
如果设置的是TCaplusValueFlag_SAMEWITHREQUEST, 则操作失败后返回和请求一致的数据, 暂时没有实现
如果设置的是TCaplusValueFlag_ALLVALUE, 不合理场景
如果设置的是TCaplusValueFlag_ALLOLDVALUE, 如果获取到了tcapsvr端的数据则返回tcpasvr端的数据,如果没有获取到tcapsvr端的数据则返回空
9. TCAPLUS_API_LIST_REPLACE_REQ
如果设置的是TCaplusValueFlag_NOVALUE, 则操作失败后不返回数据
如果设置的是TCaplusValueFlag_SAMEWITHREQUEST, 则操作失败后返回和请求一致的数据, 暂时没有实现
如果设置的是TCaplusValueFlag_ALLVALUE, 不合理场景
如果设置的是TCaplusValueFlag_ALLOLDVALUE, 如果获取到了tcapsvr端的数据则返回tcpasvr端的数据,如果没有获取到tcapsvr端的数据则返回空
@param [IN] result_flag 请求标志:
0表示: 只需返回操作执行成功与否
1表示: 返回与请求字段一致
2表示: 须返回变更记录的所有字段最新数据
3表示: 须返回变更记录的所有字段旧数据
对于batch_get请求,该字段设置为大于0时,某个key查询记录不存在或svr端产生的其它错误时会返回对应的key,
从而知道是哪个key对应的记录失败了
@retval 0 设置成功
@retval <0 失败,返回对应的错误码。通常因为未初始化。
*/
SetResultFlagForFail(result_flag byte) int
/**
@brief 如果此请求会返回多条记录,通过此接口对返回的记录做一些限制
@param [IN] limit 需要查询的记录条数, limit若等于-1表示操作或返回所有匹配的数据记录.
@param [IN] offset 记录起始编号;若设置为负值(-N, N>0),则从倒数第N个记录开始返回结果
@retval 0 设置成功
@retval <0 设置失败,具体错误参见 \link ErrorCode \endlink
@note 对于Generic类型的部分Key查询,limit表示所要获取Record的条数,offset表示所要获取Record的开始下标;
对于List类型的GetAll操作,limit表示所要获取Record的条数,offset表示所要获取Record的开始下标,
在当前版本中这些Record一定属于同一个List.
该函数仅仅对于GET_BY_PARTKEY(Generic类型的部分Key查询), UPDATE_BY_PARTKEY,
DELETE_BY_PARTKEY, LIST_GETALL(List类型的GetAll操)这4种操作类型有效。
*/
SetResultLimit(limit int32, offset int32) int32
/**
@brief 设置是否允许一个请求包可以自动响应多个应答包,仅对ListGetAll和BatchGet协议有效。
@param [IN] multi_flag 多响应包标示,1表示允许一个请求包可以自动响应多个应答包,
0表示不允许一个请求包自动响应多个应答包
@retval 0 设置成功
@retval <0 设置失败,具体错误参见 \link ErrorCode \endlink
@note 分包应答,目前只支持ListGetAll和BatchGet操作;其他操作设置该值是没有意义的,
函数会返回<0的错误码。
*/
SetMultiResponseFlag(multi_flag byte) int32
6. 响应对象(response)中的方法说明
注:此处未列出的响应对象的其它方法,即表示该方法在查询数据的场景不需要使用,误用可能会导致报错。
/*
@brief 获取响应结果
@retval int tcaplus api自定义错误码。 0,表示请求成功;非0,有错误码,可从terror.GetErrMsg(int)得到错误消息
*/
GetResult() int
/*
@brief 获取响应表名
@retval string 响应消息对应的表名称
*/
GetTableName() string
/*
@brief 获取响应appId
@retval uint64 响应消息对应的appId
*/
GetAppId() uint64
/*
@brief 获取响应zoneId
@retval uint32 响应消息对应的zoneId
*/
GetZoneId() uint32
/*
@brief 获取响应命令
@retval int 响应消息命令字,cmd包中的响应命令字
*/
GetCmd() int
/*
@brief 获取响应异步id,和请求对应
@retval uint64 响应消息对应的异步id和请求对应
*/
GetAsyncId() uint64
/*
@brief 获取本响应中结果记录条数
@retval int 响应中结果记录条数
*/
GetRecordCount() int
/*
@brief 从结果中获取一条记录
@retval *record.Record 记录指针
@retval error 错误码
*/
FetchRecord() (*record.Record, error)
/*
@brief 获取响应消息中的用户缓存信息
@retval []byte 用户缓存二进制,和请求消息中的buffer内容一致
*/
GetUserBuffer() []byte
7. 记录对象(record)中的方法说明
注:此处未列出的响应对象的其它方法,即表示该方法在查询数据的场景不需要使用,误用可能会导致报错。
- record的通用方法: ```go / @brief 获取记录版本号 @retval 记录版本号 @note 对于Generic操作表示获取Record的版本;对于List操作表示获取Record所在List的版本。 / func (r *Record) GetVersion() int32
- record可以基于TDR结构设置和提取记录
```go
/**
@brief 基于TDR描述设置record数据
@param [IN] data 基于TDR描述record接口数据,tdr的xml通过工具生成的go结构体,包含的TdrTableSt接口的一系列方法
@retval error 错误码
*/
func (r *Record) SetData(data TdrTableSt) error
/**
@brief 基于TDR描述读取record数据
@param [IN] data 基于TDR描述record接口数据,tdr的xml通过工具生成的go结构体,包含的TdrTableSt接口的一系列方法
@retval error 错误码
**/
func (r *Record) GetData(data TdrTableSt) error
- record同时支持通过SetKey SetValue接口设置记录中的字段,通过GetKey GetValue接口提取记录中的字段,但是SetKey、SetValue、GetKey、GetValue同SetData、GetData接口不可混用
- SetKey SetValue接口设置的数据,只能通过GetKey,GetValue接口读取;SetKey SetValue在使用batch命令时需要注意,record设置完成后调用Pack()把记录打包;SetData是一次性的,函数调用会自动打包,而SetKey SetValue不确定用户什么时候设置完最后一个字段,所以需要用户设置完kv后调用Pack()把记录打包;
- SetData接口设置的数据,只能通过GetData读取
/**
@brief key字段内容设置
@param [in] name 字段名称,最大长度32
@param [in] data 字段内容
@retval error 错误码
*/
func (r *Record) SetKeyInt8(name string, data int8) error
func (r *Record) SetKeyInt16(name string, data int16) error
func (r *Record) SetKeyInt32(name string, data int32) error
func (r *Record) SetKeyInt64(name string, data int64) error
func (r *Record) SetKeyFloat32(name string, data float32) error
func (r *Record) SetKeyFloat64(name string, data float64) error
func (r *Record) SetKeyStr(name string, data string) error
func (r *Record) SetKeyBlob(name string, data []byte) error
/**
@brief value字段内容设置
@param [in] name 字段名称,最大长度32
@param [in] data 字段内容
@retval error 错误码
*/
func (r *Record) SetValueInt8(name string, data int8) error
func (r *Record) SetValueInt16(name string, data int16) error
func (r *Record) SetValueInt32(name string, data int32) error
func (r *Record) SetValueInt64(name string, data int64) error
func (r *Record) SetValueFloat32(name string, data float32) error
func (r *Record) SetValueFloat64(name string, data float64) error
func (r *Record) SetValueStr(name string, data string) error
func (r *Record) SetValueBlob(name string, data []byte) error
/**
@brief key字段内容获取
@param [in] name 字段名称,最大长度32
@retval data 字段内容
@retval error 错误码
*/
func (r *Record) GetKeyInt8(name string) (int8, error)
func (r *Record) GetKeyInt16(name string) (int16, error)
func (r *Record) GetKeyInt32(name string) (int32, error)
func (r *Record) GetKeyInt64(name string) (int64, error)
func (r *Record) GetKeyFloat32(name string) (float32, error)
func (r *Record) GetKeyFloat64(name string) (float64, error)
func (r *Record) GetKeyStr(name string) (string, error)
func (r *Record) GetKeyBlob(name string) ([]byte, error)
/**
@brief value字段内容获取
@param [in] name 字段名称,最大长度32
@retval data 字段内容
@retval error 错误码
*/
func (r *Record) GetValueInt8(name string) (int8, error)
func (r *Record) GetValueInt16(name string) (int16, error)
func (r *Record) GetValueInt32(name string) (int32, error)
func (r *Record) GetValueInt64(name string) (int64, error)
func (r *Record) GetValueFloat32(name string) (float32, error)
func (r *Record) GetValueFloat64(name string) (float64, error)
func (r *Record) GetValueStr(name string) (string, error)
func (r *Record) GetValueBlob(name string) ([]byte, error)
8. 常见问题
详见错误码含义和处理方法。